{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "whjsJasuhstV"
   },
   "source": [
    "<a href=\"https://colab.research.google.com/github/jeffheaton/app_generative_ai/blob/main/t81_559_class_02_1_dev.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "euOZxlIMhstX"
   },
   "source": [
    "# T81-559: Applications of Generative Artificial Intelligence\n",
    "**Module 2: Code Generation**\n",
    "* Instructor: [Jeff Heaton](https://sites.wustl.edu/jeffheaton/), McKelvey School of Engineering, [Washington University in St. Louis](https://engineering.wustl.edu/Programs/Pages/default.aspx)\n",
    "* For more information visit the [class website](https://sites.wustl.edu/jeffheaton/t81-558/)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "d4Yov72PhstY"
   },
   "source": [
    "# Module 2 Material\n",
    "\n",
    "* **Part 2.1: Prompting for Code Generation** [[Video]](https://www.youtube.com/watch?v=HVId6kYKKgQ) [[Notebook]](t81_559_class_02_1_dev.ipynb)\n",
    "* Part 2.2: Handling Revision Prompts [[Video]](https://www.youtube.com/watch?v=APpV46tplXA) [[Notebook]](t81_559_class_02_2_multi_prompt.ipynb)\n",
    "* Part 2.3: Using a LLM to Help Debug [[Video]](https://www.youtube.com/watch?v=VPqSNb38QK0) [[Notebook]](t81_559_class_02_3_llm_debug.ipynb)\n",
    "* Part 2.4: Tracking Prompts in Software Development [[Video]](https://www.youtube.com/watch?v=oUFUuYfvXZU) [[Notebook]](t81_559_class_02_4_software_eng.ipynb)\n",
    "* Part 2.5: Limits of LLM Code Generation [[Video]](https://www.youtube.com/watch?v=dKtRI0LZSyY) [[Notebook]](t81_559_class_02_5_code_gen_limits.ipynb)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "AcAUP0c3hstY"
   },
   "source": [
    "# Google CoLab Instructions\n",
    "\n",
    "The following code ensures that Google CoLab is running and maps Google Drive if needed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true,
     "base_uri": "https://localhost:8080/"
    },
    "id": "xsI496h5hstZ",
    "outputId": "4b78d8f4-3b0e-4a47-84a3-10012ba63786"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Note: using Google CoLab\n",
      "Requirement already satisfied: langchain in /usr/local/lib/python3.10/dist-packages (0.1.14)\n",
      "Requirement already satisfied: langchain_openai in /usr/local/lib/python3.10/dist-packages (0.1.1)\n",
      "Requirement already satisfied: PyYAML>=5.3 in /usr/local/lib/python3.10/dist-packages (from langchain) (6.0.1)\n",
      "Requirement already satisfied: SQLAlchemy<3,>=1.4 in /usr/local/lib/python3.10/dist-packages (from langchain) (2.0.29)\n",
      "Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in /usr/local/lib/python3.10/dist-packages (from langchain) (3.9.3)\n",
      "Requirement already satisfied: async-timeout<5.0.0,>=4.0.0 in /usr/local/lib/python3.10/dist-packages (from langchain) (4.0.3)\n",
      "Requirement already satisfied: dataclasses-json<0.7,>=0.5.7 in /usr/local/lib/python3.10/dist-packages (from langchain) (0.6.4)\n",
      "Requirement already satisfied: jsonpatch<2.0,>=1.33 in /usr/local/lib/python3.10/dist-packages (from langchain) (1.33)\n",
      "Requirement already satisfied: langchain-community<0.1,>=0.0.30 in /usr/local/lib/python3.10/dist-packages (from langchain) (0.0.31)\n",
      "Requirement already satisfied: langchain-core<0.2.0,>=0.1.37 in /usr/local/lib/python3.10/dist-packages (from langchain) (0.1.40)\n",
      "Requirement already satisfied: langchain-text-splitters<0.1,>=0.0.1 in /usr/local/lib/python3.10/dist-packages (from langchain) (0.0.1)\n",
      "Requirement already satisfied: langsmith<0.2.0,>=0.1.17 in /usr/local/lib/python3.10/dist-packages (from langchain) (0.1.41)\n",
      "Requirement already satisfied: numpy<2,>=1 in /usr/local/lib/python3.10/dist-packages (from langchain) (1.25.2)\n",
      "Requirement already satisfied: pydantic<3,>=1 in /usr/local/lib/python3.10/dist-packages (from langchain) (2.6.4)\n",
      "Requirement already satisfied: requests<3,>=2 in /usr/local/lib/python3.10/dist-packages (from langchain) (2.31.0)\n",
      "Requirement already satisfied: tenacity<9.0.0,>=8.1.0 in /usr/local/lib/python3.10/dist-packages (from langchain) (8.2.3)\n",
      "Requirement already satisfied: openai<2.0.0,>=1.10.0 in /usr/local/lib/python3.10/dist-packages (from langchain_openai) (1.16.2)\n",
      "Requirement already satisfied: tiktoken<1,>=0.5.2 in /usr/local/lib/python3.10/dist-packages (from langchain_openai) (0.6.0)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.3.1)\n",
      "Requirement already satisfied: attrs>=17.3.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (23.2.0)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.4.1)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (6.0.5)\n",
      "Requirement already satisfied: yarl<2.0,>=1.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.9.4)\n",
      "Requirement already satisfied: marshmallow<4.0.0,>=3.18.0 in /usr/local/lib/python3.10/dist-packages (from dataclasses-json<0.7,>=0.5.7->langchain) (3.21.1)\n",
      "Requirement already satisfied: typing-inspect<1,>=0.4.0 in /usr/local/lib/python3.10/dist-packages (from dataclasses-json<0.7,>=0.5.7->langchain) (0.9.0)\n",
      "Requirement already satisfied: jsonpointer>=1.9 in /usr/local/lib/python3.10/dist-packages (from jsonpatch<2.0,>=1.33->langchain) (2.4)\n",
      "Requirement already satisfied: packaging<24.0,>=23.2 in /usr/local/lib/python3.10/dist-packages (from langchain-core<0.2.0,>=0.1.37->langchain) (23.2)\n",
      "Requirement already satisfied: orjson<4.0.0,>=3.9.14 in /usr/local/lib/python3.10/dist-packages (from langsmith<0.2.0,>=0.1.17->langchain) (3.10.0)\n",
      "Requirement already satisfied: anyio<5,>=3.5.0 in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.10.0->langchain_openai) (3.7.1)\n",
      "Requirement already satisfied: distro<2,>=1.7.0 in /usr/lib/python3/dist-packages (from openai<2.0.0,>=1.10.0->langchain_openai) (1.7.0)\n",
      "Requirement already satisfied: httpx<1,>=0.23.0 in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.10.0->langchain_openai) (0.27.0)\n",
      "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.10.0->langchain_openai) (1.3.1)\n",
      "Requirement already satisfied: tqdm>4 in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.10.0->langchain_openai) (4.66.2)\n",
      "Requirement already satisfied: typing-extensions<5,>=4.7 in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.10.0->langchain_openai) (4.10.0)\n",
      "Requirement already satisfied: annotated-types>=0.4.0 in /usr/local/lib/python3.10/dist-packages (from pydantic<3,>=1->langchain) (0.6.0)\n",
      "Requirement already satisfied: pydantic-core==2.16.3 in /usr/local/lib/python3.10/dist-packages (from pydantic<3,>=1->langchain) (2.16.3)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (3.3.2)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (3.6)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (2.0.7)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (2024.2.2)\n",
      "Requirement already satisfied: greenlet!=0.4.17 in /usr/local/lib/python3.10/dist-packages (from SQLAlchemy<3,>=1.4->langchain) (3.0.3)\n",
      "Requirement already satisfied: regex>=2022.1.18 in /usr/local/lib/python3.10/dist-packages (from tiktoken<1,>=0.5.2->langchain_openai) (2023.12.25)\n",
      "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio<5,>=3.5.0->openai<2.0.0,>=1.10.0->langchain_openai) (1.2.0)\n",
      "Requirement already satisfied: httpcore==1.* in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->openai<2.0.0,>=1.10.0->langchain_openai) (1.0.5)\n",
      "Requirement already satisfied: h11<0.15,>=0.13 in /usr/local/lib/python3.10/dist-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai<2.0.0,>=1.10.0->langchain_openai) (0.14.0)\n",
      "Requirement already satisfied: mypy-extensions>=0.3.0 in /usr/local/lib/python3.10/dist-packages (from typing-inspect<1,>=0.4.0->dataclasses-json<0.7,>=0.5.7->langchain) (1.0.0)\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "\n",
    "try:\n",
    "    from google.colab import drive, userdata\n",
    "    COLAB = True\n",
    "    print(\"Note: using Google CoLab\")\n",
    "except:\n",
    "    print(\"Note: not using Google CoLab\")\n",
    "    COLAB = False\n",
    "\n",
    "# OpenAI Secrets\n",
    "if COLAB:\n",
    "    os.environ[\"OPENAI_API_KEY\"] = userdata.get('OPENAI_API_KEY')\n",
    "\n",
    "# Install needed libraries in CoLab\n",
    "if COLAB:\n",
    "    !pip install langchain langchain_openai"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "pC9A-LaYhsta"
   },
   "source": [
    "# 2.1: Prompting for Code Generation\n",
    "\n",
    "## OpenAI for Code Generation\n",
    "\n",
    "LLMs are adept at generating code and can considerably boost programmers' productivity. This technical course requires you to create programs for the assignments. You might wonder if I consider it  \"cheating\" to utilize LLMs to help you write your homework assignments. For this course, I do not consider it cheating to use AI to help you with assignments; I expect such utilization in this course.\n",
    "\n",
    "You can use the same OpenAI LLMs that your OpenAI grants access to for code generation. You also have other options, which may give you access to even greater code generation capabilities, though OpenAI should be sufficient for this class.\n",
    "\n",
    "There are three possible LLM-based code generation tools. All three require additional fees for use.\n",
    "\n",
    "* [GitHub CoPilot](https://github.com/features/copilot)\n",
    "* [ChatGPT](https://chat.openai.com/)\n",
    "* [Amazon CodeWhisperer](https://aws.amazon.com/codewhisperer/)\n",
    "\n",
    "You can use the code below to access OpenAI for code generation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "TMF-rtxgRAea"
   },
   "outputs": [],
   "source": [
    "from langchain_core.messages import HumanMessage, SystemMessage\n",
    "from langchain_core.prompts.chat import (\n",
    "    ChatPromptTemplate,\n",
    "    HumanMessagePromptTemplate,\n",
    "    SystemMessagePromptTemplate,\n",
    ")\n",
    "from langchain_openai import ChatOpenAI\n",
    "from IPython.display import display_markdown\n",
    "\n",
    "MODEL = 'gpt-4o-mini'\n",
    "\n",
    "def generate_code(prompt):\n",
    "  messages = [\n",
    "      SystemMessage(\n",
    "          content=\"You are a helpful assistant that writes reliable computer program code.\"\n",
    "      ),\n",
    "      HumanMessage(content=prompt),\n",
    "  ]\n",
    "\n",
    "  # Initialize the OpenAI LLM with your API key\n",
    "  llm = ChatOpenAI(\n",
    "    model=MODEL,\n",
    "    temperature= 0.0,\n",
    "    n= 1)\n",
    "\n",
    "  print(MODEL)\n",
    "  print(\"Model response:\")\n",
    "  output = llm.invoke(messages)\n",
    "  display_markdown(output.content,raw=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ClPhLkGldhPt"
   },
   "source": [
    "With the above function defined, you can now generate code. The code below generates a Python function to create a Fibonacci sequence."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true,
     "base_uri": "https://localhost:8080/",
     "height": 494
    },
    "id": "ydaqwgRiH4D6",
    "outputId": "52243a3a-b06b-44e6-a95e-ca398c9865a1"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gpt-4-turbo\n",
      "Model response:\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "Here's a Python function that generates a Fibonacci sequence of length `l`. The Fibonacci sequence is a series of numbers where each number is the sum of the two preceding ones, usually starting with 0 and 1.\n",
       "\n",
       "```python\n",
       "def fibonacci_sequence(length):\n",
       "    if length <= 0:\n",
       "        return []  # Return an empty list for non-positive lengths\n",
       "    elif length == 1:\n",
       "        return [0]  # Return a list with only the first Fibonacci number\n",
       "    elif length == 2:\n",
       "        return [0, 1]  # Return the first two Fibonacci numbers\n",
       "    \n",
       "    # Start the sequence with the first two Fibonacci numbers\n",
       "    sequence = [0, 1]\n",
       "    \n",
       "    # Generate the Fibonacci sequence up to the specified length\n",
       "    while len(sequence) < length:\n",
       "        # Append the sum of the last two elements in the sequence\n",
       "        sequence.append(sequence[-1] + sequence[-2])\n",
       "    \n",
       "    return sequence\n",
       "\n",
       "# Example usage:\n",
       "length = 10  # Specify the length of the Fibonacci sequence\n",
       "print(fibonacci_sequence(length))\n",
       "```\n",
       "\n",
       "This function handles edge cases where the length is less than or equal to 0 by returning an empty list. It also handles cases where the length is 1 or 2 by returning the initial segments of the Fibonacci sequence. For any other length, it computes the sequence iteratively."
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "generate_code(\"\"\"Write Python code to return a fibonacci sequence of a length specified by the parameter l.\"\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "8fzxOCfgeKUF"
   },
   "source": [
    "## Generating Methods"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "priNIsKGgR7M",
    "outputId": "d9e826bf-f195-4a43-d459-765a473b23fc"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gpt-4-turbo\n",
      "Model response:\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "To create the `loan_amortization` function in Python that calculates the amortization schedule of a loan and returns it as a Pandas DataFrame, we need to follow these steps:\n",
       "\n",
       "1. Calculate the monthly interest rate from the annual percentage rate (APR).\n",
       "2. Calculate the monthly payment using the formula for an annuity.\n",
       "3. For each month, compute:\n",
       "   - The interest paid based on the remaining loan balance.\n",
       "   - The principal paid as the difference between the total monthly payment and the interest paid.\n",
       "   - The new remaining balance after subtracting the principal paid from the previous balance.\n",
       "4. Store each month's data in a dictionary and append it to a list.\n",
       "5. Convert the list of dictionaries into a Pandas DataFrame.\n",
       "\n",
       "Here's the Python function to achieve this:\n",
       "\n",
       "```python\n",
       "import pandas as pd\n",
       "\n",
       "def loan_amortization(loan_amount, apr, term):\n",
       "    # Convert APR to a monthly interest rate\n",
       "    monthly_interest_rate = apr / 12 / 100\n",
       "    \n",
       "    # Calculate monthly payment using the formula for an annuity\n",
       "    payment = loan_amount * (monthly_interest_rate * (1 + monthly_interest_rate) ** term) / ((1 + monthly_interest_rate) ** term - 1)\n",
       "    \n",
       "    # Initialize variables\n",
       "    remaining_balance = loan_amount\n",
       "    amortization_schedule = []\n",
       "    \n",
       "    # Calculate the schedule\n",
       "    for month in range(1, term + 1):\n",
       "        interest = remaining_balance * monthly_interest_rate\n",
       "        principal = payment - interest\n",
       "        remaining_balance -= principal\n",
       "        \n",
       "        # Ensure the last payment does not go negative\n",
       "        if remaining_balance < 0:\n",
       "            principal += remaining_balance\n",
       "            payment = principal + interest\n",
       "            remaining_balance = 0\n",
       "        \n",
       "        # Append each month's data to the list\n",
       "        amortization_schedule.append({\n",
       "            \"month\": month,\n",
       "            \"amount\": remaining_balance,\n",
       "            \"principal\": principal,\n",
       "            \"interest\": interest,\n",
       "            \"payment\": payment\n",
       "        })\n",
       "        \n",
       "        # Break the loop if balance is zero\n",
       "        if remaining_balance <= 0:\n",
       "            break\n",
       "    \n",
       "    # Create a DataFrame from the list of dictionaries\n",
       "    df = pd.DataFrame(amortization_schedule)\n",
       "    return df\n",
       "\n",
       "# Example usage:\n",
       "loan_amount = 100000  # $100,000 loan\n",
       "apr = 5  # 5% annual interest rate\n",
       "term = 360  # 30 years, 360 months\n",
       "\n",
       "df = loan_amortization(loan_amount, apr, term)\n",
       "print(df.head())  # Print the first few rows of the DataFrame\n",
       "```\n",
       "\n",
       "This function will generate the amortization schedule for a loan given the loan amount, APR, and term in months. It returns a DataFrame with columns for each month, the remaining loan amount, the principal paid, the interest paid, and the total payment for that month. Adjust the `loan_amount`, `apr`, and `term` in the example usage to see different schedules."
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "generate_code(\"\"\"\n",
    "Write a Python function named loan_amortization that accepts these parameters.\n",
    "loan_amount - The amount of the loan.\n",
    "apr - The interest rate.\n",
    "term - The number of months in the loan.\n",
    "The function should return a Pandas dataframe that contains the following columns:\n",
    "month - The current month.\n",
    "amount - The amount left on the loan.\n",
    "principal - The amount payed to the principal this month.\n",
    "interest - The amount paid in interest this month.\n",
    "payment - The total payment this month.\n",
    "Additionally, build a dictionary of columns to create the Pandas dataframe.\n",
    "\"\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "dzhI5nTfgeS4",
    "outputId": "3a3c547b-5412-447b-aaec-93283f64e569"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   month        amount   principal    interest     payment\n",
      "0      1  99879.845044  120.154956  416.666667  536.821623\n",
      "1      2  99759.189442  120.655602  416.166021  536.821623\n",
      "2      3  99638.031108  121.158334  415.663289  536.821623\n",
      "3      4  99516.367948  121.663160  415.158463  536.821623\n",
      "4      5  99394.197858  122.170090  414.651533  536.821623\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "def loan_amortization(loan_amount, apr, term):\n",
    "    # Convert APR to a monthly interest rate\n",
    "    monthly_interest_rate = apr / 12 / 100\n",
    "\n",
    "    # Calculate monthly payment using the formula for an annuity\n",
    "    payment = loan_amount * (monthly_interest_rate * (1 + monthly_interest_rate) ** term) / ((1 + monthly_interest_rate) ** term - 1)\n",
    "\n",
    "    # Initialize variables\n",
    "    remaining_balance = loan_amount\n",
    "    amortization_schedule = []\n",
    "\n",
    "    # Calculate the schedule\n",
    "    for month in range(1, term + 1):\n",
    "        interest = remaining_balance * monthly_interest_rate\n",
    "        principal = payment - interest\n",
    "        remaining_balance -= principal\n",
    "\n",
    "        # Ensure the last payment does not go negative\n",
    "        if remaining_balance < 0:\n",
    "            principal += remaining_balance\n",
    "            payment = principal + interest\n",
    "            remaining_balance = 0\n",
    "\n",
    "        # Append each month's data to the list\n",
    "        amortization_schedule.append({\n",
    "            \"month\": month,\n",
    "            \"amount\": remaining_balance,\n",
    "            \"principal\": principal,\n",
    "            \"interest\": interest,\n",
    "            \"payment\": payment\n",
    "        })\n",
    "\n",
    "        # Break the loop if balance is zero\n",
    "        if remaining_balance <= 0:\n",
    "            break\n",
    "\n",
    "    # Create a DataFrame from the list of dictionaries\n",
    "    df = pd.DataFrame(amortization_schedule)\n",
    "    return df\n",
    "\n",
    "# Example usage:\n",
    "loan_amount = 100000  # $100,000 loan\n",
    "apr = 5  # 5% annual interest rate\n",
    "term = 360  # 30 years, 360 months\n",
    "\n",
    "df = loan_amortization(loan_amount, apr, term)\n",
    "print(df.head())  # Print the first few rows of the DataFrame"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Z_ZKqu8TeQcm"
   },
   "source": [
    "```\n",
    "Write a Python function named loan_amortization that accepts these parameters.\n",
    "loan_amount - The amount of the loan.\n",
    "apr - The interest rate.\n",
    "term - The number of months in the loan.\n",
    "The function should return a Pandas dataframe that contains the following columns:\n",
    "month - The current month.\n",
    "amount - The amount left on the loan.\n",
    "principal - The amount payed to the principal this month.\n",
    "interest - The amount paid in interest this month.\n",
    "payment - The total payment this month.\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "t15LDXS9mCI_"
   },
   "source": [
    "## Generating Larger Programs\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "q2ixb46lmI4Y",
    "outputId": "b1f03758-6fcd-4b65-91d2-bdad5fdf295a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gpt-4-turbo\n",
      "Model response:\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "Creating a full 3D flight simulator with realistic graphics and sounds is a complex and extensive project that involves advanced knowledge in computer graphics, physics, and sound processing. It also requires the use of specialized libraries and possibly game engines. Below, I'll outline a simplified version of how you might start such a project using Python and the Panda3D engine, which is suitable for 3D games and simulations.\n",
       "\n",
       "### Requirements\n",
       "\n",
       "1. **Python**: Make sure Python is installed on your system.\n",
       "2. **Panda3D**: A game engine that supports Python. You can install it via pip:\n",
       "   ```bash\n",
       "   pip install panda3d\n",
       "   ```\n",
       "\n",
       "### Basic Setup\n",
       "\n",
       "Here's a basic script to create a window with a controllable camera, which is the first step in creating a flight simulator.\n",
       "\n",
       "```python\n",
       "from direct.showbase.ShowBase import ShowBase\n",
       "from panda3d.core import WindowProperties\n",
       "from direct.task import Task\n",
       "from math import pi, sin, cos\n",
       "\n",
       "class FlightSimulator(ShowBase):\n",
       "    def __init__(self):\n",
       "        super().__init__()\n",
       "\n",
       "        # Set the window title and size\n",
       "        properties = WindowProperties()\n",
       "        properties.setTitle('Cessna 152 Flight Simulator')\n",
       "        self.win.requestProperties(properties)\n",
       "\n",
       "        # Disable the default mouse-based camera control\n",
       "        self.disableMouse()\n",
       "\n",
       "        # Load the environment model\n",
       "        self.environ = self.loader.loadModel(\"models/environment\")\n",
       "        self.environ.reparentTo(self.render)\n",
       "        self.environ.setScale(0.25, 0.25, 0.25)\n",
       "        self.environ.setPos(-8, 42, 0)\n",
       "\n",
       "        # Load the Cessna 152 model (you need to have a model file)\n",
       "        self.aircraft = self.loader.loadModel(\"models/cessna152\")\n",
       "        self.aircraft.reparentTo(self.render)\n",
       "        self.aircraft.setScale(0.5)\n",
       "        self.aircraft.setPos(0, 0, 10)\n",
       "\n",
       "        # Camera control\n",
       "        self.camera.setPos(self.aircraft.getX(), self.aircraft.getY() - 30, self.aircraft.getZ() + 10)\n",
       "        self.camera.lookAt(self.aircraft)\n",
       "\n",
       "        # Task to update the simulation\n",
       "        self.taskMgr.add(self.update, \"update\")\n",
       "\n",
       "    def update(self, task):\n",
       "        # Here you would handle physics and controls\n",
       "        # For now, let's just rotate the aircraft\n",
       "        angleDegrees = task.time * 6.0\n",
       "        angleRadians = angleDegrees * (pi / 180.0)\n",
       "        self.aircraft.setPos(20 * sin(angleRadians), -20 * cos(angleRadians), 10)\n",
       "        self.camera.lookAt(self.aircraft)\n",
       "        return Task.cont\n",
       "\n",
       "app = FlightSimulator()\n",
       "app.run()\n",
       "```\n",
       "\n",
       "### Explanation\n",
       "\n",
       "1. **Environment Setup**: This script sets up a basic window and loads a static environment model.\n",
       "2. **Aircraft Model**: It assumes you have a 3D model of a Cessna 152. You would need to create or obtain a `.bam` or `.egg` file compatible with Panda3D.\n",
       "3. **Camera Control**: The camera is positioned to follow the aircraft from behind.\n",
       "4. **Basic Physics**: The `update` function currently just rotates the aircraft in a circle. You would need to replace this with actual flight physics.\n",
       "\n",
       "### Next Steps\n",
       "\n",
       "1. **Implement Flight Dynamics**: You would need to implement realistic flight dynamics. This could be done using aerodynamic equations and control surface simulations.\n",
       "2. **Add User Controls**: Implement keyboard or joystick controls to manipulate the aircraft's pitch, roll, yaw, and throttle.\n",
       "3. **Enhance Graphics**: Add textures, lighting, and shadows to make the simulation more realistic.\n",
       "4. **Sound**: Integrate engine sounds and other audio effects using Panda3D's audio management features.\n",
       "\n",
       "### Conclusion\n",
       "\n",
       "This example is a very basic starting point. A full-fledged flight simulator is a large-scale project that might require a team of developers with expertise in different areas like 3D graphics, physics, and sound design."
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "generate_code(\"\"\"\n",
    "Create a PyTorch GPU-enabled neural network for a Kaggle competition that asks me to predict the age of people in provided images.\n",
    "The images are stored at this path: /kaggle/input/applications-of-deep-learning-wustl-spring-2024/faces-age.\n",
    "The training data is in the file: /kaggle/input/applications-of-deep-learning-wustl-spring-2024/faces-age/train.csv.\n",
    "The training data has 3 columns, id, filename, and age. The field age is the target, to be predicted, numeric age in years of\n",
    "the person. The file contains the filename of the image that corresponds to each row, the images are named 1.jpg, 2.jpg, etc,\n",
    "which corresponds to both the id and the filename fields. There is also a test dataset that we must generate a submission\n",
    "dataframe for. The test data is in the file /kaggle/input/applications-of-deep-learning-wustl-spring-2024/faces-age/test.csv,\n",
    "and has the id and filename columns, but we need to generate a submit dataframe with just id and age(the prediction). Train the neural network, use early stopping and generate the submit dataframe.\n",
    "\"\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "3TjZs_TRht1n"
   },
   "source": [
    "# Module 2 Assignment\n",
    "\n",
    "You can find the first assignment here: [assignment 2](https://github.com/jeffheaton/app_generative_ai/blob/main/assignments/assignment_yourname_class2.ipynb)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3.11 (genai)",
   "language": "python",
   "name": "genai"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.8"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
